﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.Linq;
using System.Security.Policy;
using System.Text;
using System.Threading.Tasks;

namespace DrawControl.UI.Common.DrawControCenter.DrawSeal
{
    public class RingSeal : Control, IDrawControl
    {
        private bool _isDraw = false;
        private const string star = "★";
        public RingSeal():this(160,160)
        {

        }
        public RingSeal(int width, int height)
        {
            SetStyle(
        ControlStyles.ResizeRedraw
        | ControlStyles.DoubleBuffer
        | ControlStyles.UserPaint
        | ControlStyles.AllPaintingInWmPaint
        | ControlStyles.SupportsTransparentBackColor,
        true
        );
            this.ForeColor = Color.Red;
            this.BackColor = Color.Transparent;
            this.BorderColor = Color.Red;
            this.Width = width;
            this.Height = height;
            TitleFont = new Font("SimSun",13, FontStyle.Bold);
            HorizontalFont = new Font("SimSun", 13, FontStyle.Bold);
            ChordFont = new Font("SimSun", 8, FontStyle.Bold);
            StarFont=new Font("SimSun", 32, FontStyle.Bold);
            Title = "测试科技股份有限公司";
            HorizontalText = "测试专用";
            ChordText = DateTime.Now.ToString("yyyyMMddHHmmss");
            Draw();
        }
        public Color BorderColor { get; set; }
        public float BorderSize { get; set; } = 1f;
        public Image Image { get; private set; }
        public Font TitleFont { get;  set; }
        public Font HorizontalFont {  get; set; }
        public Font ChordFont { get; set; }
        public Font StarFont {  get; set; }
        public string Title {  get; set; }
        public float TitleStartAngle { get; set; } = 160f;
        public string HorizontalText {  get; set; }
        public string ChordText {  get; set; }
        public float ChordStartAngle { get; set; } = 135f;
        public Form FormType { get; set; }

        public void Save(string fileName)
        {
            Image?.Save(fileName);
        }

        public void Save(Stream stream, ImageFormat format)
        {
            Image?.Save(stream, format);
        }

        public void Draw()
        {
            Image?.Dispose();
            Image = new Bitmap(Width == 0 ? 1 : Width, Height == 0 ? 1 : Height);
            using (Graphics g = Graphics.FromImage(Image))
            {
                g.Smooth();
                g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias;
                g.Clear(this.BackColor);
                _isDraw = true;
                DrawCircle(g);
                DrawStar(g);
                DrawHorizontal(g);
                DrawTitle(g,this.Title, this.TitleStartAngle);
                DrawChord(g);
            }
            this.Invalidate();
        }
        private void DrawCircle(Graphics g)
        {
            RectangleF rect = new RectangleF(BorderSize / 2f - 0.5f, BorderSize / 2f - 0.5f, this.Width - BorderSize, this.Height - BorderSize);
            using Pen pen = new Pen(this.ForeColor, BorderSize); 
            g.DrawEllipse(pen, rect); 
        }
        /// <summary>
        /// 绘制星星
        /// </summary>
        public void DrawStar(Graphics g)
        {
            var starSize = g.MeasureString(star, StarFont);
            PointF starXy = new PointF(this.Width / 2 - starSize.Width / 2, this.Width / 2 - starSize.Height / 2);
            using var sb = new SolidBrush(this.ForeColor);
            g.DrawString(star, StarFont,sb , starXy);
        }
        public void DrawHorizontal(Graphics g)
        {
            int length = this.HorizontalText.Length;
            SizeF textSize = g.MeasureString(HorizontalText, this.HorizontalFont);
            
            //要指定的位置绘制中间文字
            PointF point = new PointF(this.Width / 2 - textSize.Width / 2, this.Width * 2 / 3);

            g.ResetTransform();
            using var sb = new SolidBrush(this.ForeColor);
            g.DrawString(HorizontalText, HorizontalFont,sb , point);
        }
        /// <summary>
        /// 绘制主题
        /// </summary>
        /// <param name="title">主题（公司名称）</param>
        /// <param name="startAngle">开始角度</param>
        private void DrawTitle(Graphics g,string title, float startAngle = 160f)
        {
            if (string.IsNullOrWhiteSpace(title)) return;

            if (Math.Cos(startAngle / 180 * Math.PI) > 0)
                throw new ArgumentException($"初始角度错误：{startAngle}(建议135-270)", nameof(startAngle));

            startAngle = startAngle % 360;//起始角度

            var length = title.Length;
            float changeAngle = (270 - startAngle) * 2 / length;//每个字所占的角度，也就是旋转角度
            var circleWidth = this.Width / 2 - this.BorderSize * 3;//字体圆形的长度
            var fontSize = g.MeasureString(title, this.TitleFont);//测量一下字体
            var per = fontSize.Width / length;//每个字体的长度

            //在指定的角度绘制字符
            void action(string t, float a)
            {
                var angleXy = a / 180 * Math.PI;
                var x = this.Width / 2 + Math.Cos(angleXy) * circleWidth;
                var y = this.Width / 2 + Math.Sin(angleXy) * circleWidth;

                DrawChar(t, (float)x, (float)y, a + 90, this.TitleFont,g);
            }

            //起始绘制角度=起始角度+旋转角度/2-字体所占角度的一半
            var angle = startAngle + changeAngle / 2 - (float)(Math.Asin(per / 2 / circleWidth) / Math.PI * 180);//起始绘制角度
            for (var i = 0; i < length; i++)
            {
                action(title[i].ToString(), angle);
                angle += changeAngle;
            }
        }
        public void DrawChord(Graphics g)
        {
            if (string.IsNullOrWhiteSpace(ChordText)) return;

            if (Math.Cos(ChordStartAngle / 180 * Math.PI) > 0)
                throw new ArgumentException($"初始角度错误：{ChordStartAngle}(建议90-135)", nameof(ChordStartAngle));

            ChordStartAngle = ChordStartAngle % 360;//起始角度

            var length = ChordText.Length;
            float changeAngle = (ChordStartAngle - 90) * 2 / length;//每个字所占的角度，也就是旋转角度
            var fontSize = g.MeasureString(ChordText, ChordFont);//测量一下字体
            var per = fontSize.Width / length;//每个字体的长度
            var circleWidth = this.Width / 2 - this.BorderSize * 2 - fontSize.Height;//字体圆形的长度

            //在指定的角度绘制字符
            void action(string t, float a)
            {
                var angleXy = a / 180 * Math.PI;
                var x = this.Width / 2 + Math.Cos(angleXy) * circleWidth;
                var y = this.Width / 2 + Math.Sin(angleXy) * circleWidth;

                DrawChar(t, (float)x, (float)y, a - 90, ChordFont, g);
            }

            //起始绘制角度=起始角度-旋转角度/2+字体所占角度的一半
            var angle = ChordStartAngle - changeAngle / 2 + (float)(Math.Asin(per / 2 / circleWidth) / Math.PI * 180);//起始绘制角度
            for (var i = 0; i < length; i++)
            {
                action(ChordText[i].ToString(), angle);
                angle -= changeAngle;
            }
        }
        /// <summary>
        /// 绘制单个字符
        /// </summary>
        /// <param name="char">字符</param>
        /// <param name="x">距离画布左边的距离</param>
        /// <param name="y">距离画布上边的距离</param>
        /// <param name="angle">选中角度，0度为右方，顺时针增加</param>
        /// <param name="font">字体</param>
        public void DrawChar(string @char, float x, float y, float angle, Font font, Graphics g)
        {
            if (string.IsNullOrEmpty(@char) || @char.Length != 1)
                throw new ArgumentException("only one char is supported", nameof(@char));

            g.ResetTransform();
            g.TranslateTransform(x, y);
            g.RotateTransform(angle);
            using var sb = new SolidBrush(this.ForeColor);
            g.DrawString(@char, font, sb, 0, 0);
        }

        protected override void OnPaint(PaintEventArgs e)
        {
            base.OnPaint(e);
            if (Image != null && _isDraw)
            {
                e.Graphics.DrawImage(Image, 0, 0, Image.Width, Image.Height);
            }
        }

        protected override void OnSizeChanged(EventArgs e)
        {
            base.OnSizeChanged(e);

            if (_isDraw)
            {
                Image?.Dispose();
                Image = new Bitmap(Width == 0 ? 1 : Width, Height == 0 ? 1 : Height);
                Draw();
            }
        }

        protected override void Dispose(bool disposing)
        {
            base.Dispose(disposing);
            Image?.Dispose();
        }
    }
}
